#pragma once
#include <memory>
#include <vector>
#include "abstract.hpp"
#include "detail.hpp"

namespace rpc
{
    typedef std::pair<std::string, int> Address;
    class JsonMessage : public BaseMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;
        //对正文进行序列化
        virtual std::string serialize() override
        {
            std::string body;
            bool ret = JSON::serialize(_body, body);
            if (ret == false)
            {
                return std::string();
            }
            return body;
        }

        //对正文进行反序列化
        virtual bool unserialize(const std::string &msg) override
        {
            return JSON::unserialize(msg, _body);
        }

    protected:
        Json::Value _body;//消息正文相关信息
    };

    //消息请求
    class JsonRequest : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonRequest>;
    };

    //消息响应
    class JsonResponse : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonResponse>;
        //检查rcode
        //大部分的响应都只有响应状态码,判断响应状态码字段是否存在,类型是否正确
        virtual bool check() override 
        {
            //检测是否存在
            if (_body[KEY_RCODE].isNull() == true)
            {
                LOG(ERROR, "响应中没有响应状态码");
                return false;
            }
            //检测类型是否正确
            if (_body[KEY_RCODE].isIntegral() == false)
            {
                LOG(ERROR, "响应状态码类型错误");
                return false;
            }
            return true;
        }

        //返回响应状态码
        virtual RCode rcode()
        {
            return (RCode)_body[KEY_RCODE].asInt();
        }

        //设置响应状态码
        virtual void setRCode(RCode rcode)
        {
            _body[KEY_RCODE] = (int)rcode;
        }
    };

    //Rpc请求
    class RpcRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;
        //rpc请求中,包含请求方法名称(字符串),参数(对象)
        /*
            |len|Mtype|IdLen|Id|body|
                 RPC_REQ         body { method:"Add",parameters:{num1:11,num2:22}}
         */
        virtual bool check() override
        {
            if (_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)
            {
                LOG(ERROR, "RPC请求中没有方法名或者方法名类型错误");
                return false;
            }
            if (_body[KEY_PARAMS].isNull() == true || _body[KEY_PARAMS].isObject() == false)
            {
                LOG(ERROR, "RPC请求中没有参数信息或参数信息类型错误");
                return false;
            }
            return true;
        }

        //获取方法
        std::string method()
        {
            return _body[KEY_METHOD].asString();
        }
        
        //设置方法
        void setMethod(const std::string &method_name)
        {
            _body[KEY_METHOD] = method_name;
        }

        //获取参数
        Json::Value params()
        {
            return _body[KEY_PARAMS];
        }

        //设置参数
        void setParams(const Json::Value &params)
        {
            _body[KEY_PARAMS] = params;
        }
    };

    //Topic请求
    class TopicRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;
        virtual bool check() override
        {
            if (_body[KEY_TOPIC_KEY].isNull() == true || _body[KEY_TOPIC_KEY].isString() == false)
            {
                LOG(ERROR, "主题请求中没有主题名或主题名称类型错误");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isIntegral() == false)
            {
                LOG(ERROR, "主题请求中没有操作类型或者操作类型的类型错误");
                return false;
            }
            //发布消息的请求->判断是否有msg
            if ((_body[KEY_OPTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH) && (_body[KEY_TOPIC_MSG].isNull()== true || _body[KEY_TOPIC_MSG].isString() == false))
            {
                LOG(ERROR, "主题消息发布请求中没有消息内容字段或消息内容类型错误");
                return false;
            }
            return true;
        }

        //获取主题名称
        std::string topicKey()
        {
            return _body[KEY_TOPIC_KEY].asString();
        }

        //设置主题名称
        void setTopicKey(const std::string &key)
        {
            _body[KEY_TOPIC_KEY] = key;
        }

        //获取主题消息
        std::string topicMsg()
        {
            return _body[KEY_TOPIC_MSG].asString();
        }

        //设置主题消息
        void setTopicMsg(const std::string &msg)
        {
            _body[KEY_TOPIC_MSG] = msg;
        }

        //获取操作类型
        TopicOptype optype()
        {
            return (TopicOptype)_body[KEY_OPTYPE].asInt();
        }

        //设置操作类型
        void setOptype(TopicOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }
    };

    //Service请求
    class ServiceRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;
        virtual bool check() override
        {
            if (_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)
            {
                LOG(ERROR, "服务请求中没有方法名或方法名称类型错误");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isIntegral() == false)
            {
                LOG(ERROR, "服务请求中没有操作类型或操作类型错误");
                return false;
            }
            //除开服务发现
            if ((_body[KEY_OPTYPE].asInt() != (int)(ServiceOptype::SERVICE_DISCOVERY)) &&
                (_body[KEY_HOST].isNull() == true || _body[KEY_HOST].isObject() == false 
                || _body[KEY_HOST][KEY_HOST_IP].isNull() == true || _body[KEY_HOST][KEY_HOST_IP].isString() == false 
                 || _body[KEY_HOST][KEY_HOST_PORT].isNull() == true || _body[KEY_HOST][KEY_HOST_PORT].isIntegral() == false))
            {
                LOG(ERROR, "服务请求中主机信息地址错误");
                return false;
            }
            return true;
        }

        std::string method()
        {
            return _body[KEY_METHOD].asString();
        }

        void setMethod(const std::string &method)
        {
            _body[KEY_METHOD] = method;
        }

        ServiceOptype optype()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }

        void setOptype(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        //获取主机信息
        Address host()
        {
            Address addr;
            addr.first = _body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }

        //设置主机信息
        void setHost(const Address &addr)
        {
            Json::Value val;
            val[KEY_HOST_IP] = addr.first;
            val[KEY_HOST_PORT] = addr.second;
            _body[KEY_HOST] = val;
        }
    };

    //Rpc响应
    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;
        virtual bool check() override
        {
            if (_body[KEY_RCODE].isNull() == true || _body[KEY_RCODE].isIntegral() == false)
            {
                LOG(ERROR, "Rpc响应中没有响应状态码或响应状态码类型错误");
                return false;
            }
            if (_body[KEY_RESULT].isNull() == true)
            {
                LOG(ERROR, "Rpc响应中没有RPC调用的结果");
                return false;
            }
            return true;
        }

        //获取结果
        Json::Value result()
        {
            return _body[KEY_RESULT];
        }

        //设置结果
        void setResult(const Json::Value &params)
        {
            _body[KEY_RESULT] = params;
        }
    };

    //主题响应
    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
    };

    //服务响应
    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;
        virtual bool check() override
        {
            if (_body[KEY_RCODE].isNull() == true || _body[KEY_RCODE].isIntegral() == false)
            {
                LOG(ERROR, "服务响应中没有方法名称或方法名称类型错误");
                return false;
            }
            if (_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isIntegral() == false)
            {
                LOG(ERROR, "服务响应中没有操作类型或操作类型的类型错误");
                return false;
            }
            if (_body[KEY_OPTYPE].asInt() == (int)(ServiceOptype::SERVICE_DISCOVERY) && 
            (_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false 
            || _body[KEY_HOST].isNull() == true || _body[KEY_HOST].isArray() == false))
            {
                LOG(ERROR, "服务发现响应中响应信息字段错误");
                return false;
            }
            return true;
        }
        
        //方法
        std::string method()
        {
            return _body[KEY_METHOD].asString();
        }

        //设置方法,表示需要发现的方法是哪个
        void setMethod(const std::string &method)
        {
            _body[KEY_METHOD] = method;
        }

        void setHost(std::vector<Address> addrs)
        {
            for (auto &addr : addrs)
            {
                Json::Value val;
                val[KEY_HOST_IP] = addr.first;
                val[KEY_HOST_PORT] = addr.second;
                _body[KEY_HOST].append(val);//append添加进主机信息
            }
        }

        std::vector<Address> hosts()
        {
            std::vector<Address> addrs;
            int sz = _body[KEY_HOST].size();
            for (int i = 0; i < sz; i++)
            {
                Address addr;
                addr.first = _body[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _body[KEY_HOST][i][KEY_HOST_PORT].asInt();
                addrs.push_back(addr);
            }
            return addrs;
        }

        //根据操作类型来区分是否需要Address
        ServiceOptype optype()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }

        void setOptype(ServiceOptype optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }
    };

    //创建消息对象的工厂模式
    class MessageFactory
    {
    public:
        static BaseMessage::ptr create(MType mtype)
        {
            switch (mtype)
            {
            case MType::REQ_RPC://Rpc请求
                return std::make_shared<RpcRequest>();
            case MType::RSP_RPC://Rpc响应
                return std::make_shared<RpcResponse>();
            case MType::REQ_TOPIC://主题请求
                return std::make_shared<TopicRequest>();
            case MType::RSP_TOPIC://主题响应
                return std::make_shared<TopicResponse>();
            case MType::REQ_SERVICE://服务请求
                return std::make_shared<ServiceRequest>();
            case MType::RSP_SERVICE://服务响应
                return std::make_shared<ServiceResponse>();
            default:
                return BaseMessage::ptr();
            }
        }

        //模板类型        
        template <typename T, typename... Args>
        static std::shared_ptr<T> create(Args &&...args)
        {
            return std::make_shared<T>(std::forward(args)...);
        }
    };

}